package com.xnyzc.lhy.order.service.impl.user.message;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xnyzc.lhy.common.entity.ParameterEnum;
import com.xnyzc.lhy.common.entity.Rv;
import com.xnyzc.lhy.common.exception.PangException;
import com.xnyzc.lhy.common.penum.EErrorCode;
import com.xnyzc.lhy.common.util.*;
import com.xnyzc.lhy.order.entity.dictionaries.OaSysDict;
import com.xnyzc.lhy.order.entity.message.OaSysMessageDriver;
import com.xnyzc.lhy.order.entity.param.user.message.*;
import com.xnyzc.lhy.order.entity.result.user.message.ResultUserMessage;
import com.xnyzc.lhy.order.entity.user.message.OaSysMessage;
import com.xnyzc.lhy.order.mapper.dictionaries.OaSysDictMapper;
import com.xnyzc.lhy.order.mapper.message.OaSysMessageDriverMapper;
import com.xnyzc.lhy.order.mapper.message.OaSysMessageInappMapper;
import com.xnyzc.lhy.order.mapper.user.message.OaSysMessageMapper;
import com.xnyzc.lhy.order.service.oss.IOaFileService;
import com.xnyzc.lhy.order.service.user.message.IOaSysMessageService;
import com.xnyzc.lhy.resource.entity.jpush.OaJpushConfig;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.*;

/**
 * <p>
 * 用户-消息 服务实现类
 * </p>
 *
 * @author bin
 * @since 2019-07-19
 */
@Slf4j
@Service
public class OaSysMessageServiceImpl extends ServiceImpl<OaSysMessageMapper, OaSysMessage> implements IOaSysMessageService {

    /**
     * 已读
     */
    private final Integer READ = 1;

    /**
     * 未读
     */
    private final Integer NOT_READ = 0;

    @Autowired
    private OaSysMessageMapper oaSysMessageMapper;

    @Autowired
    private OaSysDictMapper oaSysDictMapper;

    @Autowired
    private IOaFileService iOaFileService;

    @Autowired
    private OaSysMessageInappMapper oaSysMessageInappMapper;

    @Autowired
    private OaSysMessageDriverMapper oaSysMessageDriverMapper;

    /**
     * 根据用户id与消息类型查询相应的消息列表
     *
     * @param userId      用户id
     * @param messageType 消息类型 （0：系统消息、1：活动消息）
     * @param current     当前页
     * @return
     */
    @Override
    public IPage<OaSysMessage> selectUserMessagePage(Long userId, Integer messageType, long current) {
        IPage<OaSysMessage> iPage = new Page<>();
        iPage.setCurrent(current);
        IPage<OaSysMessage> page = oaSysMessageMapper.selectPage(
                iPage,
                Wrappers.<OaSysMessage>lambdaQuery()
                        .eq(OaSysMessage::getUserType, "1")
                        .eq(OaSysMessage::getMessageType, messageType)
                        .eq(OaSysMessage::getUserId, userId)
                        .orderByAsc(OaSysMessage::getIsRead)
                        .orderByDesc(OaSysMessage::getCreateTime)
        );
        if (page.getRecords().size() <= 0) {
            page.setRecords(new ArrayList<>());
            return page;
        }
        page.setRecords(this.list2List(page.getRecords()));
        return page;
    }

    /**
     * 获取系统消息列表
     *
     * @return
     */
    @Override
    public Rv selectSystemMessageList(SystemMessageDTO systemMessageDTO) {
        QueryWrapper queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(OaSysDict.TYPE, "message_type");
        queryWrapper.select(OaSysDict.VALUE, OaSysDict.LABEL, OaSysDict.EXPAND1);
        List<OaSysDict> oaSysDictList = oaSysDictMapper.selectList(queryWrapper);
        Integer program = oaSysMessageMapper.queryMessageCount(systemMessageDTO.getDriverId());
        String dateString=getDateString();
        systemMessageDTO.setTime(dateString);
        Integer inapp = oaSysMessageInappMapper.queryInAppMessageCount(systemMessageDTO);
        Integer messageStatus=program+inapp;
        List<Map<String, Object>> resultMapList = new ArrayList<>();
        for (OaSysDict oaSysDict : oaSysDictList) {
            Map<String, Object> map = new HashMap<>(3);
            DriverMessageParam item =getDriverMessageDispose(oaSysDict,systemMessageDTO.getDriverId());
            map.put("icon", iOaFileService.getFileUrl(Long.valueOf(oaSysDict.getExpand1())));
            map.put("title", oaSysDict.getLabel());
            map.put("messageType", Integer.parseInt(oaSysDict.getValue()));
            map.put("type", systemMessageDTO.getType());
            map.put("jumpUrl", "");
            if (CheckUtil.objIsEmpty(item)) {
                map.put("date", "");
            } else {
                if (CheckUtil.objIsEmpty(item.getMessageType())) {
                    map.put("date", "");
                } else {
                    if (oaSysDict.getValue().equals(item.getMessageType().toString())) {
                        if (CheckUtil.objIsNotEmpty(item.getCreateTime())) {
                            double date = DateUtil.dateSubtractBuffer(System.currentTimeMillis(), item.getCreateTime().getTime());
                            if (date / 60 < 24) {
                                if (date < 60) {
                                    map.put("date", (int) date + "分钟前");
                                }
                                if (date >= 60) {
                                    date = date / 60;
                                    map.put("date", (int) date + "小时前");
                                }
                            } else {
                                map.put("date", DateUtil.convertDateToString(item.getCreateTime()));
                            }

                        } else {
                            map.put("date", "");
                        }
                    } else {
                        map.put("date", "");
                    }
                }
            }
            resultMapList.add(map);
        }
        System.out.println(DateUtil.dateSubtract(System.currentTimeMillis(), System.currentTimeMillis()));
        Map<String, Object> resultMap = new HashMap<>(2);
        resultMap.put("messageStatus", messageStatus);
        resultMap.put("systemMessageList", resultMapList);
        return Rv.wrap(resultMap);
    }

    /**
     * 获取活动消息列表
     *
     * @return
     */
    @Override
    public Rv selectActivityMessageList(SystemMessageDTO systemMessageDTO) {
        String dateString=getDateString();
        systemMessageDTO.setTime(dateString);
        Integer messageStatus = oaSysMessageInappMapper.queryActivityMessageCount(systemMessageDTO);
        List<Map<String, Object>> resultMapList = new ArrayList<>();
        List<DriverMessageResults> itemList = oaSysMessageInappMapper.queryActivityMessage(systemMessageDTO);
        if(!itemList.isEmpty()){
            for(DriverMessageResults item:itemList){
                Map<String, Object> map = new HashMap<>(3);
                map.put("icon", iOaFileService.getFileUrl(Long.valueOf(item.getMessageGraphPath())));
                map.put("title", item.getMessageTitle());
                map.put("messageType", 5);
                if(CheckUtil.objIsNotEmpty(item.getJumpUrl())){
                    map.put("jumpUrl", item.getJumpUrl());
                }else{
                    map.put("jumpUrl", "");
                }
                map.put("type", systemMessageDTO.getType());
                if (CheckUtil.objIsEmpty(item)) {
                    map.put("date", "");
                } else {
                    if (CheckUtil.objIsNotEmpty(item.getCreateTime())) {
                        double date = DateUtil.dateSubtractBuffer(System.currentTimeMillis(), item.getCreateTime().getTime());
                        if (date / 60 < 24) {
                            if (date < 60) {
                                map.put("date", (int) date + "分钟前");
                            }
                            if (date >= 60) {
                                date = date / 60;
                                map.put("date", (int) date + "小时前");
                            }
                        } else {
                            map.put("date", DateUtil.convertDateToString(item.getCreateTime()));
                        }

                    } else {
                        map.put("date", "");
                    }
                }
                resultMapList.add(map);
            }
        }
        Map<String, Object> resultMap = new HashMap<>(2);
        resultMap.put("messageStatus", messageStatus);
        resultMap.put("systemMessageList", resultMapList);
        return Rv.wrap(resultMap);
    }

    public String getDateString(){
        Date currentTime = new Date();
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String dateString = formatter.format(currentTime);
        return dateString;
    }

    public DriverMessageParam getDriverMessageDispose(OaSysDict oaSysDict,Long driverId){
        List<DriverMessageParam> resultList=new ArrayList<>();
        DriverMessageParam result=new DriverMessageParam();
        // 程序推送
        DriverMessageParam program = oaSysMessageMapper.querySystemMessage(oaSysDict.getValue(), driverId);
        // 应用内推送 其他消息
        if(oaSysDict.getValue().equals(ParameterEnum.THREE.getTypeName())){
            String dateString=getDateString();
            SystemMessageDTO systemMessageDTO=new SystemMessageDTO();
            systemMessageDTO.setDriverId(driverId);
            systemMessageDTO.setTime(dateString);
            DriverMessageParam inapp = oaSysMessageInappMapper.querySystemMessage(systemMessageDTO);
            if(CheckUtil.objIsNotEmpty(inapp)){
                DriverMessageParam inappResult=new DriverMessageParam();
                inappResult.setMessageType(ParameterEnum.THREE.getType());
                inappResult.setCreateTime(inapp.getCreateTime());
                resultList.add(inappResult);
            }
        }
        if(CheckUtil.objIsNotEmpty(program)){
            DriverMessageParam programResult=new DriverMessageParam();
            programResult.setMessageType(program.getMessageType());
            programResult.setCreateTime(program.getCreateTime());
            resultList.add(programResult);
        }
        if(!resultList.isEmpty()){
            //排序
            Collections.sort(resultList, new Comparator() {
                @Override
                public int compare(Object o1, Object o2) {
                    DriverMessageParam w1 = (DriverMessageParam) o1;
                    DriverMessageParam w2 = (DriverMessageParam) o2;
                    return w2.getCreateTime().compareTo(w1.getCreateTime());
                }
            });
            result.setCreateTime(resultList.get(0).getCreateTime());
            result.setMessageType(resultList.get(0).getMessageType());
        }
        return result;
    }


    @Override
    public Rv selectSystemMessage(DriverMessageParam driverMessageParam) {
        driverMessageParam.setDriverId(TokenUtil.getTokenUserId());
        List<OaSysMessage> messagesList  = new ArrayList<>();
        // 其他消息
        if(driverMessageParam.getMessageType() == 3){
            String dateString=getDateString();
            driverMessageParam.setTime(dateString);
            messagesList  = oaSysMessageInappMapper.queryMessageDate(driverMessageParam);
        }
        // 消息列表
        List<OaSysMessage> oaSysMessages = oaSysMessageMapper.queryMessageDate(driverMessageParam);
        if(!messagesList.isEmpty()){
            oaSysMessages.addAll(messagesList);
        }
        // 返回结果
        List<OaSysMessageMap> oaSysMessageMaps = new ArrayList<>();
        // 遍历消息列表
        for (OaSysMessage oaSysMessage : oaSysMessages) {
            // 新建接参实体
            OaSysMessageMap oaSysMessageMap = new OaSysMessageMap();
            // 新建消息集合
            List<OaSysMessagePutMap> oaSysMessagePutMaps = new ArrayList<>();
            if (CheckUtil.collectionIsEmpty(oaSysMessageMaps)) {
                double newDate = DateUtil.dateSubtractBuffer(System.currentTimeMillis(), oaSysMessage.getCreateTime().getTime());
                // 如果是当天，那么新建一个集合
                if (newDate < 60) {
                    // 分钟
                    oaSysMessageMap.setTime((int) newDate + "分钟前");
                } else {
                    if (newDate >= 60 && newDate <= 60* 24) {
                        // 小时
                        newDate = newDate / 60;
                        oaSysMessageMap.setTime((int) newDate + "小时前");
                    } else {
                        oaSysMessageMap.setTime(oaSysMessageMap.getDate());
                    }
                }
                // 添加
                add(oaSysMessageMap, oaSysMessage, oaSysMessagePutMaps, oaSysMessageMaps);
            } else {
                int count = 0;
                for (OaSysMessageMap newOaSysMessageMap : oaSysMessageMaps) {
                    if (oaSysMessage.getTag().equals(newOaSysMessageMap.getDate())) {
                        // 若是同一天
                        double newDate = DateUtil.dateSubtractBuffer(System.currentTimeMillis(), oaSysMessage.getCreateTime().getTime());
                        if (newDate / 60 <= 24 && oaSysMessage.getTag().equals(DateUtil.convertToStringCustom(new Date(), "MM-dd"))) {
                            // 如果是当天，那么新建一个集合
                            if (newDate < 60) {
                                // 分钟
                                oaSysMessageMap.setTime((int) newDate + "分钟前");
                            } else {
                                if (newDate >= 60 && newDate <= 60* 24) {
                                    // 小时
                                    newDate = newDate / 60;
                                    oaSysMessageMap.setTime((int) newDate + "小时前");
                                } else {
                                    oaSysMessageMap.setTime(oaSysMessageMap.getDate());
                                }
                            }
                            // 并集
                            add(oaSysMessageMap, oaSysMessage, oaSysMessagePutMaps, oaSysMessageMaps);
                            break;
                        } else {
                            newOaSysMessageMap.getOaSysMessagePutMaps().add(BeanUtil.copyProperties(oaSysMessage, OaSysMessagePutMap.class));
                        }
                    } else {
                        // 若不是同一天
                        count++;
                    }
                }
                // 循环结束后，判断天的条件是否成立
                if (count == oaSysMessageMaps.size()) {
                    // 若没有此天的组，那么添加一个新组
                    oaSysMessageMap.setTime(oaSysMessage.getTag());
                    add(oaSysMessageMap, oaSysMessage, oaSysMessagePutMaps, oaSysMessageMaps);
                }
            }
        }

        // 不行了，这接口改不来，拿结果重新遍历一次，处理小时问题
        List<OaSysMessageMap> resultMessage = new ArrayList<>();

        int count = 0;
        for (int i = 0; i < oaSysMessageMaps.size(); i ++) {
            if (oaSysMessageMaps.get(i).getDate().equals(DateUtil.convertToStringCustom(new Date(), "MM-dd"))) {
                if (CheckUtil.collectionIsEmpty(resultMessage)) {
                    resultMessage.add(oaSysMessageMaps.get(i));
                } else {
                    for (int j = count; j < resultMessage.size(); j ++) {
                        if (resultMessage.get(j).getTime().equals(oaSysMessageMaps.get(i).getTime())) {
                            resultMessage.get(j).getOaSysMessagePutMaps().add(oaSysMessageMaps.get(i).getOaSysMessagePutMaps().get(0));
                        } else {
                            resultMessage.add(oaSysMessageMaps.get(i));
                            count ++;
                            break;
                        }
                    }
                }
            } else {
                resultMessage.add(oaSysMessageMaps.get(i));
            }
        }

        return Rv.wrap(resultMessage);
    }

    private void add(
            OaSysMessageMap oaSysMessageMap,
            OaSysMessage oaSysMessage,
            List<OaSysMessagePutMap> oaSysMessagePutMaps,
            List<OaSysMessageMap> oaSysMessageMaps
    ) {

        // 从消息列表中获取时间,并且按日分组
        if (CheckUtil.strIsEmpty(oaSysMessageMap.getTime())) {
            oaSysMessageMap.setTime(oaSysMessage.getTag());
        }
        oaSysMessageMap.setDate(oaSysMessage.getTag());

        oaSysMessagePutMaps.add(BeanUtil.copyProperties(oaSysMessage, OaSysMessagePutMap.class));

        oaSysMessageMap.setOaSysMessagePutMaps(oaSysMessagePutMaps);

        // 并集
        oaSysMessageMaps.add(oaSysMessageMap);

    }

    /**
     * 已读消息
     *
     * @param messageId 消息ID
     */
    @Override
    public Rv readMessage(Long messageId) {
        QueryWrapper<OaSysMessage> oaSysMessageQueryWrapper = new QueryWrapper<>();
        oaSysMessageQueryWrapper.eq(OaSysMessage.MESSAGE_ID, messageId);
        oaSysMessageQueryWrapper.select(OaSysMessage.VERSION);
        Integer result=0;
        OaSysMessage message=oaSysMessageMapper.selectOne(oaSysMessageQueryWrapper);
        if(CheckUtil.objIsNotEmpty(message)){
            Long version = 0L;
            version=message.getVersion();
            OaSysMessage oaSysMessage = new OaSysMessage();
            oaSysMessage.setMessageId(messageId);
            oaSysMessage.setIsRead(READ);
            oaSysMessage.setVersion(version);
            result = oaSysMessageMapper.updateById(oaSysMessage);
        }else{
            OaSysMessageDriver messageDriver=oaSysMessageDriverMapper.selectById(messageId);
            if(CheckUtil.objIsNotEmpty(messageDriver)){
                OaSysMessageDriver oaSysMessage = new OaSysMessageDriver();
                oaSysMessage.setMessageDriverId(messageId);
                oaSysMessage.setIsRead(READ);
                result = oaSysMessageDriverMapper.updateById(oaSysMessage);
            }
        }
        if (result > 0) {
            Map<String, Integer> resultMap = new HashMap<>(1);
            resultMap.put("isSuccess", result);
            return Rv.wrap(resultMap);
        } else {
            throw PangException.create(EErrorCode.messageReadFiled);
        }
    }

    /**
     * 保存消息
     *
     * @param oaSysMessage
     * @return
     */
    @Override
    public Rv saveMessage(OaSysMessage oaSysMessage) {

        if (CheckUtil.objIsEmpty(oaSysMessage.getPushCode())) {
            throw PangException.create(EErrorCode.missingArg);
        }

        if (CheckUtil.objIsEmpty(oaSysMessage.getDriverId())) {
            throw PangException.create(EErrorCode.missingArg);
        }

        Date now = new Date();
        log.info("------ 开始添加消息 ------");
        Map<String, String> map = oaSysMessageMapper.selectMessageTitle(oaSysMessage.getPushCode());
        oaSysMessage.setMessageId(IDUtil.nextId());
        oaSysMessage.setUserId(oaSysMessage.getDriverId());
        oaSysMessage.setUserType(1);
        oaSysMessage.setMessageTitle(map.get(OaJpushConfig.TITLE));
        oaSysMessage.setJumpMark(map.get(OaJpushConfig.JUMP_KEY));
        oaSysMessage.setCreateTime(now);
        oaSysMessage.setUpdateTime(now);
        oaSysMessage.setCreateUser(oaSysMessage.getDriverId());
        oaSysMessage.setUpdateUser(oaSysMessage.getDriverId());
        Integer result = oaSysMessageMapper.insert(oaSysMessage);
        log.info("------ 结束添加消息 ------");
        return Rv.wrap(result);
    }

    /**
     * 讲查询结果放进出参实体列表中
     *
     * @param list
     * @return
     */
    private List list2List(List<OaSysMessage> list) {
        List resultUserMessages = new ArrayList<>();
        for (OaSysMessage oaSysMessage : list) {
            ResultUserMessage resultUserMessage = new ResultUserMessage();
            resultUserMessage.setMessageId(oaSysMessage.getMessageId());
            resultUserMessage.setUserId(oaSysMessage.getUserId());
            resultUserMessage.setUserType(oaSysMessage.getUserType());
            resultUserMessage.setMessageContent(oaSysMessage.getMessageContent());
            resultUserMessage.setMessageTitle(oaSysMessage.getMessageTitle());
            resultUserMessage.setJumpMark(oaSysMessage.getJumpMark());
            resultUserMessage.setIsRead(oaSysMessage.getIsRead());
            resultUserMessage.setCreateTime(DateFormatUtils.format(oaSysMessage.getCreateTime(), "yyyy-MM-dd hh:mm:ss"));
            resultUserMessages.add(resultUserMessage);
        }
        return resultUserMessages;
    }
}
